<template>
  <div class="quest-timer">
    <div class="row1">
      <el-tag size="small" type="info">{{ quest.type }}</el-tag>
      <span class="need">目标：{{ minRequired }}s</span>
      <span class="elapsed">已读：{{ elapsed }}s</span>
    </div>
    <el-progress :percentage="progressPercent" :status="progressStatus" :text-inside="true" :stroke-width="18" />
    <div class="actions">
      <el-button size="small" @click="toggle()" :type="running ? 'warning' : 'primary'">
        {{ running ? '暂停' : (started ? '继续' : '开始') }}
      </el-button>
      <el-button size="small" type="success" :disabled="!canFinish || finishing" :loading="finishing" @click="finish">
        完成
      </el-button>
      <el-button size="small" @click="reset" :disabled="finishing">重置</el-button>
    </div>
  </div>
  
</template>

<script setup>
import { ref, computed, onMounted, onBeforeUnmount, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { getToken } from '@/utils/auth'
import { exploreApi } from '@/api/explore'

const props = defineProps({
  quest: { type: Object, required: true },
  // 初次渲染是否自动开始
  autoStart: { type: Boolean, default: false },
  // 达标后是否自动完成
  autoFinish: { type: Boolean, default: true },
  // 进度上报节流（秒）
  throttleSec: { type: Number, default: 5 }
})

const emit = defineEmits(['started', 'progressed', 'finished'])

const running = ref(false)
const started = ref(false)
const finishing = ref(false)
const hasFinished = ref(false)
const elapsed = ref(0) // 本地累计秒
const lastTick = ref(0)
const lastReported = ref(0)
let timer = null

const storageKey = computed(() => {
  const t = getToken() || 'guest'
  const suffix = typeof t === 'string' ? t.slice(-12) : 'guest'
  return `explore:questTimer:${props.quest?.id}:${suffix}`
})
const minRequired = computed(() => Number(props.quest?.requirement_json?.min_read_seconds || 0))

const progressPercent = computed(() => {
  if (minRequired.value <= 0) return 100
  return Math.min(100, Math.floor((elapsed.value / minRequired.value) * 100))
})
const progressStatus = computed(() => (elapsed.value >= minRequired.value && minRequired.value > 0) ? 'success' : undefined)
const canFinish = computed(() => elapsed.value >= minRequired.value)

// 本地持久化
function loadPersist() {
  try {
    const raw = localStorage.getItem(storageKey.value)
    if (raw) {
      const obj = JSON.parse(raw)
      elapsed.value = Number(obj.elapsed || 0)
      started.value = !!obj.started
      lastReported.value = Number(obj.lastReported || 0)
    }
    // 与服务端回显对齐：如果 props.quest.progress_json 提供了 elapsed，则以更大者为准
    const serverElapsed = Number(props.quest?.progress_json?.elapsed || 0)
    if (!Number.isNaN(serverElapsed) && serverElapsed > elapsed.value) {
      elapsed.value = serverElapsed
      // 若服务端已有进度，视为已开始（仅当用户已登录）
      if (getToken()) started.value = true
    }
  } catch {}
}
function savePersist() {
  try {
    localStorage.setItem(storageKey.value, JSON.stringify({
      elapsed: elapsed.value,
      started: started.value,
      lastReported: lastReported.value
    }))
  } catch {}
}
function clearPersist() {
  try { localStorage.removeItem(storageKey.value) } catch {}
}

async function ensureStartedRemote() {
  if (started.value) return
  const token = getToken()
  if (!token) {
    ElMessage.warning('请先登录以开始任务')
    // 不置 started，保持未开始状态
    return
  }
  try {
    await exploreApi.startQuest(props.quest.id)
    started.value = true
    emit('started', props.quest.id)
    savePersist()
  } catch (e) {
    // 不置 started；可能是未认证或服务端拒绝
    const msg = e?.response?.data?.detail || '无法开始任务，请稍后再试'
    ElMessage.error(msg)
  }
}

function tick() {
  const now = Date.now()
  if (!lastTick.value) {
    lastTick.value = now
    return
  }
  const deltaSec = Math.floor((now - lastTick.value) / 1000)
  if (deltaSec > 0) {
    elapsed.value += deltaSec
    lastTick.value += deltaSec * 1000
    savePersist()
    // 仅在已成功开始后才上报/自动完成
    if (started.value) {
      maybeReport()
      // 达标即自动完成（可配置）
      if (props.autoFinish && canFinish.value && !finishing.value && !hasFinished.value) {
      // 避免频繁触发，直接调用一次 finish
      finish()
      }
    }
  }
}

async function maybeReport(force = false) {
  if (!started.value) return
  const inc = elapsed.value - lastReported.value
  if (inc <= 0) return
  if (!force && inc < props.throttleSec) return
  try {
    // 发送绝对累计时间，便于服务端直接校验 progress_json.elapsed
    await exploreApi.reportProgress(props.quest.id, { payload: { elapsed: elapsed.value } })
    lastReported.value = elapsed.value
    savePersist()
    emit('progressed', { questId: props.quest.id, seconds: inc, total: elapsed.value })
  } catch (e) {
    // 报错先不打断计时，仅提示
    console.warn('reportProgress failed', e)
  }
}

async function start() {
  if (running.value) return
  await ensureStartedRemote()
  if (!started.value) {
    running.value = false
    return
  }
  running.value = true
  lastTick.value = Date.now()
  timer = setInterval(tick, 300)
}
function pause() {
  if (!running.value) return
  running.value = false
  if (timer) { clearInterval(timer); timer = null }
  maybeReport(true)
}
function toggle() { running.value ? pause() : start() }
function reset() {
  pause()
  elapsed.value = 0
  lastReported.value = 0
  clearPersist()
}

async function finish() {
  if (!started.value) { ElMessage.warning('请先开始任务并保持登录'); return }
  if (!canFinish.value || finishing.value || hasFinished.value) return
  finishing.value = true
  try {
    pause()
    await maybeReport(true)
    await exploreApi.finishQuest(props.quest.id, {})
    clearPersist()
    emit('finished', props.quest.id)
    ElMessage.success('任务完成')
    hasFinished.value = true
  } catch (e) {
    ElMessage.error(e?.response?.data?.detail || '完成失败，可能未达到要求时长')
  } finally {
    finishing.value = false
  }
}

function onVisibilityChange() {
  if (document.hidden) {
    pause()
  } else {
    if (started.value) start()
  }
}

function beforeUnloadHandler() { try { maybeReport(true) } catch {} }

function onAuthOut() {
  // 注销或过期：暂停并标记未开始，防止误上报/完成
  try { pause() } catch {}
  started.value = false
  savePersist()
}

function onAuthLogin() {
  // 登录后无需自动开始，等待用户显式开始
}

onMounted(() => {
  loadPersist()
  if (props.autoStart) start()
  document.addEventListener('visibilitychange', onVisibilityChange)
  window.addEventListener('beforeunload', beforeUnloadHandler)
  window.addEventListener('auth-expired', onAuthOut)
  window.addEventListener('auth-logout', onAuthOut)
  window.addEventListener('auth-login', onAuthLogin)
})

onBeforeUnmount(() => {
  pause()
  document.removeEventListener('visibilitychange', onVisibilityChange)
  window.removeEventListener('beforeunload', beforeUnloadHandler)
  window.removeEventListener('auth-expired', onAuthOut)
  window.removeEventListener('auth-logout', onAuthOut)
  window.removeEventListener('auth-login', onAuthLogin)
})

watch(() => props.quest?.id, () => {
  // 任务切换时复位
  reset()
  // 切换后立即尝试读取服务端进度初始化
  loadPersist()
})

// 暴露方法（如父组件需要）
defineExpose({ start, pause, reset })
</script>

<style scoped>
.quest-timer { display:flex; flex-direction:column; gap:8px; }
.row1 { display:flex; align-items:center; gap:8px; color:#555; font-size:13px; }
.actions { display:flex; gap:8px; }
</style>
